import { readFile, writeFile, mkdir } from 'fs/promises'
import path from 'path'

/**
 * 读取模板文件的内容。
 * @param {string} templatePath - 模板文件的路径。
 * @returns {Promise<string>} - 模板文件的内容。
 * @throws {Error} - 当读取文件出现错误时抛出异常。
 */
async function readTemplate(templatePath) {
  try {
    // 以 UTF-8 编码读取模板文件
    return await readFile(templatePath, 'utf8')
  } catch (error) {
    // 打印读取模板文件时的错误信息
    console.error('读取模板文件时出错:', error)
    throw error
  }
}

/**
 * 替换模板中的占位符信息。
 * @param {string} template - 模板文件的内容。
 * @param {Object} replacements - 替换信息的键值对对象。
 * @returns {string} - 替换后的模板内容。
 */
function replaceTemplate(template, replacements) {
  let result = template
  // 遍历替换信息的键值对
  for (const [key, value] of Object.entries(replacements)) {
    // 构建占位符格式
    const placeholder = `{{${key}}}`
    // 使用正则表达式全局替换模板中的占位符
    result = result.replace(new RegExp(placeholder, 'g'), value)
  }
  return result
}

/**
 * 将内容写入新文件。
 * @param {string} filePath - 新文件的路径。
 * @param {string} content - 要写入文件的内容。
 * @throws {Error} - 当创建目录或写入文件出现错误时抛出异常。
 */
async function writeNewFile(filePath, content) {
  // 获取文件所在的目录路径
  const dir = path.dirname(filePath)
  try {
    // 递归创建目录
    await mkdir(dir, { recursive: true })
    // 将内容写入文件
    await writeFile(filePath, content)
    // 打印文件写入成功的信息
    console.log(`文件已新增: ${filePath}`)
  } catch (error) {
    // 打印写入文件时的错误信息
    console.error('文件新增时出错:', error)
    throw error
  }
}

/**
 * 根据模板文件生成新文件。
 * @param {string} templatePath - 模板文件的路径。
 * @param {string} outputPath - 输出文件的路径。
 * @param {Object} replacements - 替换信息的键值对对象。
 */
export async function generateFileFromTemplate(templatePath, outputPath, replacements) {
  try {
    // 读取模板文件内容
    const template = await readTemplate(templatePath)
    // 替换模板中的占位符信息
    const newContent = replaceTemplate(template, replacements)
    // 将替换后的内容写入新文件
    await writeNewFile(outputPath, newContent)
  } catch (error) {
    // 打印生成文件过程中的错误信息
    console.error('生成文件过程中出现错误:', error)
  }
}
